#include "linked_list.h"

linked_list *ll_new()
{
	linked_list *ll = (linked_list *)malloc(sizeof(linked_list));
	ll->last = NULL;
	ll->first = NULL;
	ll->lenght = 0;
	return ll;
}

void ll_delete(void *ll, void free_f(void *))
{
	linked_list *l = (linked_list *) ll;
	l->lenght=0;
	ll_node *i = l->first;
	ll_node *aux;
	void *data;

	while(i != NULL)
	{
		aux = i;
		i = i->next;
		data = aux->data;
		if(free_f != NULL) free_f(data);
		free(aux);
	}
	free(ll);
}

int ll_is_empty(const linked_list *ll)
{
	return (ll->lenght == 0);
}

int ll_length(const linked_list *ll)
{
	return ll->lenght;
}

void ll_insert_first(linked_list *ll, void *data)
{
	ll_node *aux = (ll_node *)malloc(sizeof(ll_node));

	aux->data = data;
	aux->next = ll->first;
	aux->previous = NULL;
	if(!ll_is_empty(ll)) ll->first->previous = aux;
	else ll->last = aux;
	ll->first = aux;

	(ll->lenght)++;
}

void ll_insert_last(linked_list *ll, void *data)
{
	ll_node *aux = (ll_node *)malloc(sizeof(ll_node));

	aux->data = data;
	aux->next = NULL;
	aux->previous = ll->last;
	if(!ll_is_empty(ll)) ll->last->next = aux;
	else ll->first = aux;
	ll->last = aux;

	(ll->lenght)++;
}

void ll_remove_last(linked_list *ll, void free_f(void *))
{
    ll_node *aux = ll->first;
    if(aux != NULL)
    {
        ll->first = aux->next;
        if(ll->first != NULL) ll->first->previous = NULL;
        free_f(aux->data);
        free(aux);
    }
}

void ll_remove_first(linked_list *ll, void free_f(void *))
{
    ll_node *aux = ll->last;
    if(aux != NULL)
    {
        ll->last = aux->previous;
        if(ll->last != NULL) ll->last->next = NULL;
        free_f(aux->data);
        free(aux);
    }
}

void *ll_get_index(linked_list *ll, int index)
{
	int count = 0;
	ll_node *i = ll->first;

	if(index >= ll->lenght) return NULL;

	while(i != NULL && count < index)
	{
		count++;
		i = i->next;
	}

	return i->data;
}

